package btc

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"errors"
	"io/ioutil"
	"math/big"
	"net/http"
	"strconv"

	"gitee.com/coin-kit/btc-tx"
	"gitee.com/coin-kit/btc-tx/address"
	"github.com/astaxie/beego/httplib"
	"github.com/tidwall/gjson"
)

type UnspentJson1 struct {
	Amount   uint64 `json:"value"`
	PkScript string `json:"script"`
	TxHash   string `json:"tx_hash"`
	Index    uint32 `json:"tx_output_n"`
}

type UnspentJson struct {
	Txrefs             []*UnspentJson1 `json:"txrefs"`
	Unconfirmed_txrefs []*UnspentJson1 `json:"unconfirmed_txrefs"`
}

func GetCoinByAddress(add string) ([]*btctx.Coin, error) {
	var coin []*btctx.Coin
	var jsondata UnspentJson
	url := "http://api.blockcypher.com/v1/btc/main/addrs/" + add + "?unspentOnly=true&includeScript=true"
	resp, err := http.Get(url)
	if err != nil {
		return coin, errors.New("获取未花费余额失败" + err.Error())
	}
	defer resp.Body.Close()
	input, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return coin, errors.New("获取未花费余额失败" + err.Error())
	}
	json.Unmarshal([]byte(input), &jsondata)

	for _, v := range jsondata.Txrefs {
		var coin0 btctx.Coin
		coin0.Amount = v.Amount
		coin0.PkScript = v.PkScript
		coin0.TxHash = v.TxHash
		coin0.Index = v.Index
		coin = append(coin, &coin0)
	}

	for _, v := range jsondata.Unconfirmed_txrefs {
		var coin0 btctx.Coin
		coin0.Amount = v.Amount
		coin0.PkScript = v.PkScript
		coin0.TxHash = v.TxHash
		coin0.Index = v.Index
		coin = append(coin, &coin0)
	}
	return coin, nil
}

func PayTo(from string, to string, amount, fee float64) (string, error) {
	coins, err := GetCoinByAddress(from)
	if err != nil {
		return "", err
	}
	//构建交易
	build := btctx.NewBuilder()
	build.SetParams(address.BitcoinMain)
	build.SetCoins(coins)
	build.SetFee(uint64(fee * 100000000.0))
	build.SetRefund(from)
	build.AddTxOut(to, uint64(amount*100000000.0))
	raw_tx, err := build.Build()
	if err != nil {
		return "", err
	}
	// 编码到base64并附加类型头
	buf := bytes.NewBuffer(nil)
	buf.WriteByte(byte(0x01))
	buf.Write(raw_tx)
	b64_tx := base64.RawStdEncoding.EncodeToString(buf.Bytes())
	return b64_tx, nil

}

func Broadcast(rawtx string) (string, error) {
	url := "https://api.blockcypher.com/v1/btc/main/txs/push?token=ffffb5d652164444aaaa2b6ba40433cc"
	post := httplib.Post(url)

	post.JSONBody(&map[string]string{"tx": rawtx})
	resp, err := post.DoRequest()

	if err != nil {
		return "", errors.New("请求广播接口错误" + err.Error())
	}
	input, err := ioutil.ReadAll(resp.Body)
	obj := gjson.ParseBytes(input)

	if resp.StatusCode != 201 {
		return "", errors.New(string(input))
	}

	return obj.Get("hash").String(), nil
}

func Getaddressbalance(add string) float64 {
	url := "http://api.blockcypher.com/v1/btc/main/addrs/" + add + "/balance"
	resp, err := http.Get(url)
	if err != nil {
		return 0
	}
	defer resp.Body.Close()
	input, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return 0
	}
	obj := gjson.ParseBytes([]byte(input))
	balance := obj.Get("balance").String()

	var cou = new(big.Float)
	cou.SetString(balance)
	cou = cou.Quo(cou, big.NewFloat(100000000.0))
	v2, _ := strconv.ParseFloat(cou.String(), 64)
	return v2
}
